package com.talent.web.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.talent.web.config.security.TalentUserDetails;
import com.talent.web.enums.PermissionType;
import com.talent.web.enums.ResponseEnum;
import com.talent.web.exception.TalentException;
import com.talent.web.mapper.SysMenuMapper;
import com.talent.web.mapper.SysUserMapper;
import com.talent.web.model.convertor.MenuConvertor;
import com.talent.web.model.dto.SysMenuDto;
import com.talent.web.model.entity.SysMenu;
import com.talent.web.model.vo.Meta;
import com.talent.web.model.vo.SysMenuVo;
import com.talent.web.service.ISysMenuService;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * @ClassName：ResponseEnum
 * @Author: hszhou
 * @Date: 2024/10/21 13:35
 * @Description: 菜单接口实现类
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    private SysUserMapper userMapper;

    public SysMenuServiceImpl(SysUserMapper userMapper){
        this.userMapper =userMapper;
    }

    @Override
    public void save(SysMenuDto menuDto) {
        SysMenu sysMenu = MenuConvertor.INSTANCE.dtoToPo(menuDto);
         this.baseMapper.insert(sysMenu);
    }

    @Override
    @Transactional
    public void deleteMenuById(Long id) {

        List<SysMenuVo> child = getMenuByParentId(id);
        if(CollectionUtil.isEmpty(child)){
            this.baseMapper.deleteById(id);
        }
        for (SysMenuVo sysMenuVo : child) {
            deleteMenuById(sysMenuVo.getId());
        }
    }

    @Override
    public void update(SysMenuDto menuDto) {
        Long id = menuDto.getId();
        SysMenu sysMenu = this.baseMapper.selectById(id);
        SysMenu update = MenuConvertor.INSTANCE.update(menuDto, sysMenu);
        this.baseMapper.updateById(update);
    }

    @Override
    public List<SysMenuVo> getMenuByParentId(Long parentId) {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getParentId,parentId);
        List<SysMenu> sysMenus = this.baseMapper.selectList(queryWrapper);
        return MenuConvertor.INSTANCE.poListsToVoList(sysMenus);
    }

    @Override
    public List<SysMenuVo> getCurrentMenu() {
       TalentUserDetails sysUser = (TalentUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
       Long userId = sysUser.getId();
        List<SysMenu> sysMenus = userMapper.getPermissions(userId);
        List<SysMenuVo> menuVoList =sysMenus.stream()
                .filter(e->e.getType()== PermissionType.MENU.getCode())
                .map(e->{
                    Meta meta = new Meta(e.getLabel());
                    SysMenuVo menuVo = MenuConvertor.INSTANCE.poToVo(e);
                    menuVo.setMeta(meta);
                    return menuVo;
                })
                .collect(Collectors.toList());
        //step2：利用父节点分组，所有部门的父 Id 进行分组，把所有的子节点 List 集合都找出来并一层层分好组
        Map<Long, List<SysMenuVo>> menuListMap = menuVoList.stream()
                .collect(Collectors.groupingBy(SysMenuVo::getParentId));
        //step3：关键一步，关联上子部门，将子部门的 List 集合经过遍历一层层地放置好，最终会得到完整的部门父子关系 List 集合
        menuVoList.forEach(e -> {
            List<SysMenuVo> menuVos = menuListMap.get(e.getId());
            if(menuVos!=null){
                e.setChildren(menuVos);
            }else{
                e.setChildren(new ArrayList<>());
            }

        });
        //step4：过滤出顶级部门，即所有的子部门数据都归属于一个顶级父部门 Id
        List<SysMenuVo> resultList = menuVoList.stream()
                .filter(e -> PermissionType.P.getCode().toString().equals(e.getParentId().toString()))
                .map(e->{
                    Meta meta = new Meta(e.getLabel());
                    e.setMeta(meta);
                    return e;
                })
                .collect(Collectors.toList());

        return Optional.of(resultList).orElse(null);
    }

    @Override
    public List<SysMenuVo> lists() {
       return list(true);
    }

    @Override
    public List<SysMenuVo> option() {

        return list(false);

    }

    @Override
    public SysMenuVo detail(Long id) {
        SysMenu sysMenu = this.baseMapper.selectById(id);
        if(null==sysMenu){
            throw new TalentException(ResponseEnum.DATA_NOT_FOUND);
        }
        return MenuConvertor.INSTANCE.poToVo(sysMenu);
    }

    private List<SysMenuVo>list(boolean includeBt){

        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();

        if(!includeBt){
            queryWrapper.ne(SysMenu::getType,2);
        }
        List<SysMenu> sysMenus = this.baseMapper.selectList(queryWrapper);
        List<SysMenuVo> menuVoList =sysMenus.stream()
                .map(MenuConvertor.INSTANCE::poToVo)
                .collect(Collectors.toList());
        //step2：利用父节点分组，所有部门的父 Id 进行分组，把所有的子节点 List 集合都找出来并一层层分好组
        Map<Long, List<SysMenuVo>> menuListMap = menuVoList.stream()
                .collect(Collectors.groupingBy(SysMenuVo::getParentId));
        //step3：关键一步，关联上子部门，将子部门的 List 集合经过遍历一层层地放置好，最终会得到完整的部门父子关系 List 集合
        menuVoList.forEach(e -> {
            List<SysMenuVo> menuVos = menuListMap.get(e.getId());
            if(menuVos!=null){
                e.setChildren(menuVos);
            }else{
                e.setChildren(new ArrayList<>());
            }

        });
        //step4：过滤出顶级部门，即所有的子部门数据都归属于一个顶级父部门 Id
        List<SysMenuVo
                > resultList = menuVoList.stream()
                .filter(e -> PermissionType.P.getCode().toString().equals(e.getParentId().toString()))
                .collect(Collectors.toList());
        return Optional.of(resultList).orElse(null);
    }

}
